package com.union.vehicleassistant.util;

import android.content.Context;
import android.text.TextUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Iterator;
import java.util.Locale;
import java.util.Properties;

public class FileTypeUtils {

    protected static final String MIMETYPES_PROPERTIES = "FileTypes.properties";
    protected static Properties mFileTypes;
    private static FileTypeUtils fileTypeUtils;

    private FileTypeUtils(Context context) {
        try {
            mFileTypes = new Properties();
            mFileTypes.load(context.getAssets().open(MIMETYPES_PROPERTIES));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static FileTypeUtils getInstance(Context appContext) {
        if (fileTypeUtils == null) {
            fileTypeUtils = new FileTypeUtils(appContext);
        }
        return fileTypeUtils;
    }

    public String getFileType(File file) {
        if (file == null) {
            return null;
        }
        if (!file.exists() || file.length() < 11) {
            return null;
        }
        String header = get10ByteHeader(file).toUpperCase(Locale.ROOT);
        String fileSuffix = mFileTypes.getProperty(header);
        /*
         * 优化处理：在不同的设备上同样类型的文件，文件头前面内容未必一致，可能只有前几个一致，后面就不同了
         * （例如：jpg类型文件，在不同手机上，lennovo k900前10个是一致的，但是MI3只有前5个字符一致，后面是不一样的，所有一些情况进行特殊处理）当整个头文件失败后，
         * 在进行前5个字符截取对比处理，优化具体如下：
         */
        if (TextUtils.isEmpty(fileSuffix)) {
            Iterator<Object> keyList = mFileTypes.keySet().iterator();
            //并不是所有的文件格式前10 byte（jpg）都一致，前五个byte一致即可
            String key, keySearchPrefix = header.substring(0, 5);
            while (keyList.hasNext()) {
                key = (String) keyList.next();
                if (key.contains(keySearchPrefix)) {
                    fileSuffix = mFileTypes.getProperty(key);
                    break;
                }
            }
        }

        //前5个字符截取对比处理没有找到，则进行特殊处理
        if (TextUtils.isEmpty(fileSuffix)) {
            header = get3ByteHeader(file);
            fileSuffix = mFileTypes.getProperty(header);
        }

        return fileSuffix;
    }

    public String getFileType(byte[] bytes) {
        if (bytes == null || bytes.length < 11) {
            return null;
        }

        String header = bytesToHexString(subarray(bytes, 0, 10));
        String fileSuffix = mFileTypes.getProperty(header);
        /*
         * 优化处理：在不同的设备上同样类型的文件，文件头前面内容未必一致，可能只有前几个一致，后面就不同了
         * （例如：jpg类型文件，在不同手机上，lennovo k900前10个是一致的，但是MI3只有前5个字符一致，后面是不一样的，所有一些情况进行特殊处理）当整个头文件失败后，
         * 在进行前5个字符截取对比处理，优化具体如下：
         */
        if (TextUtils.isEmpty(fileSuffix)) {
            Iterator keyList = mFileTypes.keySet().iterator();
            //并不是所有的文件格式前10 byte（jpg）都一致，前五个byte一致即可
            String key, keySearchPrefix = header.substring(0, 5);
            while (keyList.hasNext()) {
                key = (String) keyList.next();
                if (key.contains(keySearchPrefix)) {
                    fileSuffix = mFileTypes.getProperty(key);
                    break;
                }
            }
        }

        //前5个字符截取对比处理没有找到，则进行特殊处理
        if (TextUtils.isEmpty(fileSuffix)) {
            header = bytesToHexString(subarray(bytes, 0, 3));
            fileSuffix = mFileTypes.getProperty(header);
        }

        return fileSuffix;

    }

    public byte[] subarray(final byte[] array, int startIndexInclusive, int endIndexExclusive) {
        if (array == null) {
            return null;
        }
        if (startIndexInclusive < 0) {
            startIndexInclusive = 0;
        }
        if (endIndexExclusive > array.length) {
            endIndexExclusive = array.length;
        }
        final int newSize = endIndexExclusive - startIndexInclusive;
        if (newSize <= 0) {
            return new byte[0];
        }

        final byte[] subarray = new byte[newSize];
        System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
        return subarray;
    }

    private String get10ByteHeader(File file) {
        InputStream input = null;
        String value = null;
        try {
            input = new FileInputStream(file);
            byte[] b = new byte[10];
            input.read(b, 0, b.length);
            value = bytesToHexString(b);
            input.close();
        } catch (Exception e) {
        } finally {
        }
        return value;
    }

    private String get3ByteHeader(File file) {
        InputStream input = null;
        String value = null;
        try {
            input = new FileInputStream(file);
            byte[] b = new byte[3];
            input.read(b, 0, b.length);
            value = bytesToHexString(b);
            input.close();
        } catch (Exception e) {
        } finally {
        }
        return value;
    }

    private String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder();
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }

}